//数据类型
//布尔类型
let married:boolean = true;
//数字类型
let age:number = 16;
//字符串类型
let firstName:string = 'zhang';
//数组类型
let arr1:number[] = [1,2,3];
arr1.push(4);
let arr2:Array<number>=[4,5,6];
//元组类型(tuple)
//元组表示一个已知数量和类型的数组
//元组的长度是固定的，但是类型是可以是多种
let position:[number,number] = [100,100];
let person:[string,number]=['zhangsan',18.888]
console.log(person[0].length)
console.log(person[1].toFixed(2))
//长度为 "2" 的元组类型 "[string, number]" 在索引 "2" 处没有元素
//person[2]
//元组每一项都可以是不同的类型，而数组每一项类型相同
//元组有预定义的长度，数组没有长度限制
//元组用于表示一个固定的结构，而数组表示的是一个列表

//枚举类型(enum)
//事件考虑一个变量的所有的可能的值，尽量用自然语言表示它的每一个值
//比如性别 月份 星期 颜色 单位 学历
enum Gender{
    MALE,//0
    FEMALE//1
}
console.log(`李雷是${Gender.MALE}`);//0
console.log(`梅梅是${Gender.FEMALE}`);//1

enum Day{
    MONEY=1,
    TUESDAY=2
}
console.log(`今天是${Day.MONEY}`)
//常量枚举
//常量枚举和普通 枚举的区别是它会在编译阶段删除，并不能包含计算成员

const enum Color{
    Red,
    Yellow,
    Blue
}
let myColors = [Color.Red,Color.Yellow,Color.Blue];
console.log(myColors)
//any
//any是任意类型
//any就是可以赋值给任意类型
//如果类型转换遇到困难，数据结构太复杂多变，真的不知道怎么定义
//let root:any = document.getElementById('root');
//!非空断言，我肯定root不为null
//root!.style.color = 'red';

//null和undefined
//null和undefined是其它类型的子类型，可以赋值给其它的类型
//前提是tsconfig.json中strictNullChecks为false ,不进行严格的null检查 
//strictNullChecks=true 不能将null和undefined赋给其它类型
//strictNullChecks=false 可以将null和undefined赋给其它类型
//不能将类型“null”分配给类型“string”
// 子类型 动物  狗  狗是动物子类型
//如果类型A是类型B的子类型，那么你可以在期望B类型的地方使用A类型的值，不会出错，这种关系
//称为is a,表示A是一个B
//A=狗 B=动物
//我需要一个动物(父类型)，一个子类型的值可以满足要求

//let a:string = null;
//不能将类型“undefined”分配给类型“number”
//let b:number = undefined;
//如果strictNullChecks=true,null和undefined只能赋给自己的类型
let c:null = null;
let d:undefined = undefined;

//void 空
//空表示没有任何类型
//当一个函数没有返回值，TS会认为它的返回值类型为void
//给函数定义参数的类型和返回值的类型
//其声明类型不为 "void" 或 "any" 的函数必须返回值。
function hello(name:string,age:number):void{
   console.log(`hello`,name)
}

//never
// never是其它类型的子类型，代表永远不可能出现的值
//如果一个函数中肯定会抛了一个错误，那么永远不会返回值了
function fail():never{
    console.log(1)
    throw new Error('出错了');//出现报错，异常结束，永远不可能走到最后了
    console.log(2)
}
//如果代码中出现在死循环，那么也是never
//返回never的函数，必须无法到达(unreachable)的终点
function loop():never{
    console.log(1)
    while(true){}
    console.log(2)
}

//strictNullChecks
//ts中,null undefined都是任何类型的有效值，正常来说无法检测它们是否被 正确使用
function fn(x:number|string){
    //类型守卫 通过一定的条件更细化的确定某个变量的值
   if(typeof x === 'number'){
      console.log(x.toFixed(2))
   }else if(typeof x === 'string'){
    console.log(x.length)
   }else{
    console.log(x);//never 永远不可能出现这种情况
   }
}
/**
 * never void进行对比
 * void可以被赋值为undefined类型的值，never则是一个不包含值的类型，任何类型的值都不能赋值给never变量
 * 有void返回值的类型的函数是可以正常运行的，有never类型的函数不会正常进行，或者中间报错异常退出或者死循环
 */
let a:void = undefined;
//let bb:void = null;
//let cc:never =undefined;

//Symbol
//Symbol是一种新的原始的数据类型，它用来创建一个唯一的值
const sym1 = Symbol('key');
const sym2 = Symbol('key');
//此比较似乎是无意的，因为类型“typeof sym1”和“typeof sym2”没有重叠。
//console.log(sym1 === sym2)

//BigInt
//使用BitInt可以安全地存储大整数
const maxNumber = Number.MAX_SAFE_INTEGER;
console.log(maxNumber)
console.log(maxNumber+1 === maxNumber+2)
//找不到名称“BigInt”。是否需要更改目标库? 请尝试将 “lib” 编译器选项更改为“es2020”或更高版本。ts(2583)
let bigIntMax = BigInt(Number.MAX_SAFE_INTEGER)
//运算符“+”不能应用于类型“bigint”和“1”
//n这个后缀表示一个BigInt字面量
console.log(bigIntMax+1n === bigIntMax+2n)

//类型 推断
//是指编程语言中自动根据值推导出类型的能力
//未定义的时候推论成any
//如果赋值了，就会从值的类型推论出变量的类型
let username = 'zhangsan';
let age2 = 18;

//包装对象wrapper object
//js里数据类型分2种 一种是原始的数据，一种是对象类型
//原始类型没有属性
let name1 = 'zhufeng';
console.log(name1.toUpperCase())
console.log(new String(name1).toUpperCase())

let num2 = 1;
console.log(new Number(num2).toFixed())
//当调用基本类型的的方法的时候，JS会在原始类型和对象类型之间做一个迅速的强制的转换
//标识符或关键字不能紧跟在数字字面量之后
//console.log(1.toFixed(2))

//联合类型
//联合类型 union types 表示取值可以为多种类型中的一种
let name3:number|string|boolean;
//console.log(name3)
//name3=1;
name3='';
//name3=true;'
//name3=1;

//类型断言
//类型断言将一个联合类型指定为了一个更加具体的类型
//console.log((name3 as number).toFixed(2))
//console.log((name3 as string ).length)
//字面量类型和类型字面量
const up:'Up' = 'Up';
const down:'Down' = 'Down';

//字符串字面量和联合类型
//字符串字面量类型用来约束取值只能是某几个字符串中的一个，联合类型是指取值为某几个类型中的一个类型
//字符串字面量
let a4:'a'|'b'|'c'='c';
let a5:string|number = '2';
